package cn.sciento.transfer.app.service.impl;

import cn.sciento.common.STongService;
import com.fasterxml.jackson.core.JsonProcessingException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.StringUtils;
import cn.sciento.core.redis.RedisHelper;
import cn.sciento.transfer.app.service.TransferRedisService;
import cn.sciento.transfer.domain.entity.ConsDbConfig;
import cn.sciento.transfer.domain.entity.ConsTenantConfig;
import cn.sciento.transfer.domain.entity.ProducerConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

@Service
public class TransferRedisServiceImpl implements TransferRedisService {
  public static final String HDTT_KEY_PREFIX = "hdtt:config:";
  
  public static final String PRODUCER = "producer";
  
  public static final String CONSUMER = "consumer";
  
  public static final String SPLIT = ":";
  
  private static final Logger LOGGER = LoggerFactory.getLogger(TransferRedisServiceImpl.class);
  
  @Autowired
  private RedisHelper redisHelper;
  
  public void addProducerToRedis(ProducerConfig producerConfig) {
    Assert.isTrue((StringUtils.isNotEmpty(producerConfig.getServiceCode()) && 
        StringUtils.isNotEmpty(producerConfig.getTableName())), "error.data_invalid");
    String json = toJson(producerConfig);
    Assert.isTrue(StringUtils.isNotEmpty(json), "error.data_invalid");
    StringBuilder redisKey = new StringBuilder();
    redisKey.append("hdtt:config:").append(producerConfig.getServiceCode()).append(":").append(producerConfig.getTableName());
    String hashKey = "producer";
    addToRedis(redisKey.toString(), hashKey, json);
  }
  
  public void addConsumerToRedis(String serviceCode, String tableName, ConsDbConfig consDbConfig) {
    Assert.isTrue((StringUtils.isNotEmpty(serviceCode) && 
        StringUtils.isNotEmpty(tableName) && 
        StringUtils.isNotEmpty(consDbConfig.getConsumerService()) && 
        StringUtils.isNotEmpty(consDbConfig.getConsumerTable()) && 
        StringUtils.isNotEmpty(consDbConfig.getConsumerDb()) && null != consDbConfig
        .getConsumerDsId()), "error.data_invalid");
    String json = toJson(consDbConfig);
    Assert.isTrue(StringUtils.isNotEmpty(json), "error.data_invalid");
    StringBuilder redisKey = new StringBuilder();
    StringBuilder hashKey = new StringBuilder();
    redisKey.append("hdtt:config:").append(serviceCode).append(":").append(tableName);
    hashKey.append("consumer").append(":").append(consDbConfig.getConsumerService()).append(":")
      .append(consDbConfig.getConsumerTable()).append(":").append(consDbConfig.getConsumerDsId())
      .append(":").append(consDbConfig.getConsumerDb());
    addToRedis(redisKey.toString(), hashKey.toString(), json);
  }
  
  public void removeProducerFromRedis(ProducerConfig producerConfig) {
    Assert.isTrue((StringUtils.isNotEmpty(producerConfig.getServiceCode()) && 
        StringUtils.isNotEmpty(producerConfig.getTableName())), "error.data_invalid");
    StringBuilder redisKey = new StringBuilder();
    redisKey.append("hdtt:config:").append(producerConfig.getServiceCode()).append(":")
      .append(producerConfig.getTableName());
    String hashKey = "producer";
    deleteFromRedis(redisKey.toString(), hashKey);
  }
  
  public void removeConsumerFromRedis(String serviceCode, String tableName, ConsDbConfig consDbConfig) {
    Assert.isTrue((StringUtils.isNotEmpty(serviceCode) && 
        StringUtils.isNotEmpty(tableName) && 
        StringUtils.isNotEmpty(consDbConfig.getConsumerService()) && 
        StringUtils.isNotEmpty(consDbConfig.getConsumerTable()) && 
        StringUtils.isNotEmpty(consDbConfig.getConsumerDb()) && null != consDbConfig
        .getConsumerDsId()), "error.data_invalid");
    StringBuilder redisKey = new StringBuilder();
    StringBuilder hashKey = new StringBuilder();
    redisKey.append("hdtt:config:").append(serviceCode).append(":").append(tableName);
    hashKey.append("consumer").append(":").append(consDbConfig.getConsumerService()).append(":")
      .append(consDbConfig.getConsumerTable()).append(":").append(consDbConfig.getConsumerDsId())
      .append(":").append(consDbConfig.getConsumerDb());
    deleteFromRedis(redisKey.toString(), hashKey.toString());
  }
  
  public void deleteAll() {
    this.redisHelper.deleteKeysWithPrefix("hdtt:config:");
  }
  
  public List<ConsDbConfig> queryAllConsDbConfig(ProducerConfig producerConfig) {
    StringBuilder redisKey = new StringBuilder();
    redisKey.append("hdtt:config:").append(producerConfig.getServiceCode()).append(":").append(producerConfig.getTableName());
    Map<String, String> maps = this.redisHelper.hshGetAll(redisKey.toString());
    List<ConsDbConfig> consDbConfigList = new ArrayList<>();
    for (Map.Entry<String, String> entry : maps.entrySet()) {
      if (((String)entry.getKey()).startsWith("consumer"))
        consDbConfigList.add(this.redisHelper.fromJson(entry.getValue(), ConsDbConfig.class)); 
    } 
    return consDbConfigList;
  }
  
  public List<ConsTenantConfig> queryAllConsTenantConfig(ProducerConfig producerConfig, ConsDbConfig consDbConfig) {
    return null;
  }
  
  private String toJson(Object object) {
    try {
      return RedisHelper.getObjectMapper().writeValueAsString(object);
    } catch (JsonProcessingException e) {
      LOGGER.error("write Value As String With Error", (Throwable)e);
      return null;
    } 
  }
  
  private void addToRedis(String redisKey, String hashKey, String json) {
    this.redisHelper.setCurrentDatabase(STongService.Platform.REDIS_DB.intValue());
    this.redisHelper.hshPut(redisKey, hashKey, json);
    this.redisHelper.clearCurrentDatabase();
  }
  
  private void deleteFromRedis(String redisKey, String hashKey) {
    this.redisHelper.setCurrentDatabase(STongService.Platform.REDIS_DB.intValue());
    this.redisHelper.hshDelete(redisKey, new Object[] { hashKey });
    this.redisHelper.clearCurrentDatabase();
  }
}
